/*
 * Copyright (c) 2018.
 * This file was written by Fancyears·Milos·Malvis @connor. Any question/bug you can't post to 1243093366@qq.com.
 * ALL RIGHTS RESERVED.
 */
package org.fancyears.proxy;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

import org.fancyears.annotation.Component;
import org.fancyears.annotation.Service;

/**
 * 代理初始化一部分Service层的字段，可用于直接生成Dao层和Service层 在直接定义自身为字段的情况下，
 * 不予以生成该对象的字段，否则会造成内存溢出 <br/>
 * <br/>
 * 如果一个字段同时被{@see Component}和{@see Service}所注释，则认为改字段为Component的组件对象 <br/>
 * <br/>
 * 如果属性和具体的类都定义了{@see Component}或{@see Service}注解，优先使用属性上的注解值进行属性代理 <br/>
 * <br/>
 * 该类不对静态属性和transient关键字修饰的属性进行初始化
 * 
 * @author: Fancyears·Milos·Malvis
 * @CreateDate: 2019年1月17日 下午1:20:07
 */

public class ServiceProxy {
	/**
	 * 直接进行属性代理生成
	 * 
	 * @param clz 具体的对象
	 */
	public static <T> void doProxy(T clz) {
		Field[] fields = clz.getClass().getDeclaredFields();
		if (fields != null && fields.length > 0) {
			for (Field field : fields) {
				/** 过滤静态属性 **/
				if (Modifier.isStatic(field.getModifiers())) {
					continue;
				}
				/** 过滤transient 关键字修饰的属性 **/
				if (Modifier.isTransient(field.getModifiers())) {
					continue;
				}
				Class<?> proxyClz = null;
				/**
				 * 监测Dao层，优先使用属性字段上的dao层定义
				 */
				if (field.isAnnotationPresent(Component.class)) {
					Component r = field.getAnnotation(Component.class);
					proxyClz = r.target();
				}
				/** 直接在dao层和实现类中进行关联，则直接使用全局的dao层实现类 */
				else if (field.getType().isAnnotationPresent(Component.class)) {
					Component r = field.getType().getAnnotation(Component.class);
					proxyClz = r.target();
				}
				/**
				 * 监测service层
				 */
				else if (field.isAnnotationPresent(Service.class)) {
					Service s = field.getAnnotation(Service.class);
					proxyClz = s.serviceClass();
				}
				/** 直接在service层和实现类中进行关联，则直接使用全局的service层实现类 */
				else if (field.getType().isAnnotationPresent(Service.class)) {
					Service s = field.getType().getAnnotation(Service.class);
					proxyClz = s.serviceClass();
				}
				/**
				 * 没有注解注释，必须手动初始化
				 */
				else {
					System.out.println("字段" + field + "没有加上注解，需要自身实现初始化");
					continue;
				}
				field.setAccessible(true);
				Class<?> tt = field.getType();
				/* 不能反复初始化自身,否则造成内存溢出 */
				if (proxyClz.getCanonicalName().equals(clz.getClass().getCanonicalName())) {
					continue;
				}
				if (tt.isInterface()) {
					Object proxy;
					try {
						/**
						 * 产生一个被代理对象，目前代理类中不进行特殊的操作，具体查阅{@see ServiceInvocation}
						 */
						proxy = Proxy.newProxyInstance(proxyClz.getClassLoader(), new Class[] { tt },
								new ServiceInvocation(proxyClz.newInstance()));
						field.set(clz, proxy);
					} catch (IllegalArgumentException | InstantiationException | IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}
